package com.fdb.efp.nls.service.impl;

import com.fdb.efp.nls.service.facade.NlsQueueSoltComnService;
import com.fdb.efp.nls.service.facade.queue.NlsProcessRuleService;
import com.fdb.efp.nls.service.facade.sx.NlsCreditInfoService;
import com.fdb.efp.nls.service.impl.sx.CreditSoltServiceImpl;
import com.fdb.efp.nls.service.impl.yed.apply.bean.ZXQueryBean;
import com.fdb.efp.nls.service.vo.queue.NlsProcessBizVO;
import com.fdb.efp.nls.service.vo.sx.NlsCreditInfoVO;
import com.fdb.basic.framework.core.exception.BizException;
import com.fdb.basic.framework.core.exception.ESBException;
import com.fdb.basic.framework.core.util.DateTool;
import com.fdb.basic.framework.core.util.DateUtility;
import com.fdb.basic.framework.core.util.TimeUtil;
import com.fdb.basic.framework.core.util.Try;
import com.fdb.cdp.pboc.service.facade.CreditQueryDetailService;
import com.fdb.cdp.pboc.service.facade.ZXHtmlInfoService;
import com.fdb.cdp.pboc.service.facade.ZXJsonInfoService;
import com.fdb.cdp.pboc.service.vo.CreditQueryDetailVO;
import com.fdb.cdp.pboc.service.vo.ZXHtmlInfoVO;
import com.fdb.cdp.pboc.service.vo.ZXJsonInfoVO;
import com.fdb.efp.nls.service.facade.PrdInfoService;
import com.fdb.efp.nls.service.facade.PrdSoltRuleService;
import com.fdb.efp.nls.service.facade.SCfgParamService;
import com.fdb.efp.nls.service.vo.PrdInfoVO;
import com.fdb.efp.console.service.vo.SCfgParamVO;
import com.fdb.efp.nls.service.vo.YedUploadRecordVO;
import com.fdb.efp.nls.service.facade.yed.YedUploadService;
import com.fdb.efp.esb.service.bo.req.ZXCXA01QueryReports;
import com.fdb.efp.esb.service.bo.req.hlw.ReqAlarmJudgementBean;
import com.fdb.efp.esb.service.bo.resp.hlw.RespAlarmJudgementBean;
import com.fdb.efp.esb.service.facade.EsbInvokeWrapper;
import com.fdb.efp.esb.service.facade.hlw.AlarmJudgementService;
import com.fdb.efp.esb.service.facade.zx.NewZXService;
import com.fdb.efp.esb.service.vo.zx.ZXVO;
import com.fdb.efp.rule.service.facade.RuleCallService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.*;
import java.net.InetAddress;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @description:优e贷二代征信规则服务
 * @date:2020年7月29日11:39:06
 * @author:zhangxican
 */
@Service("YedZXRuleService")
public class YedZXRuleServiceImpl extends CreditSoltServiceImpl {

    private static final Logger log = LoggerFactory.getLogger(YedZXRuleServiceImpl.class);

    @Autowired
    @Qualifier("ruleCallService")
    private RuleCallService ruleService;
    @Autowired
    @Qualifier("nlsProcessRuleService")
    private NlsProcessRuleService nlsProcessRuleService;
    @Autowired
    @Qualifier("prdSoltRuleService")
    private PrdSoltRuleService prdSoltRuleService;
    @Autowired
    @Qualifier("prdInfoService")
    private PrdInfoService prdInfoService;
    @Autowired
    @Qualifier("zxJsonInfoService")
    private ZXJsonInfoService zxJsonInfoService;
    @Autowired
    @Qualifier("zxCXA01Service")
    private NewZXService<ZXCXA01QueryReports> zxCXA01Service;
    @Autowired
    @Qualifier("sCfgParamService")
    private SCfgParamService sCfgParamService;
    @Autowired
    private ZXHtmlInfoService zxHtmlInfoService;
    @Autowired
    private YedUploadService yedUploadService;
    @Autowired
    private CreditQueryDetailService creditQueryDetailService;

    @Autowired
    @Qualifier("nlsQueueSoltComnService")
    private NlsQueueSoltComnService nlsQueueSoltComnService;
    @Autowired
    private NlsCreditInfoService nlsCreditInfoService;

    @Value("${yed_zxreport_save_path}")
    private String filePath;

    private static AtomicInteger zxCount = new AtomicInteger(1);

    @Override
    public void doExecute(NlsProcessBizVO nlsProcessBizVo, NlsCreditInfoVO nlsCreditInfoVO) throws Exception {
        String applySeq = nlsProcessBizVo.getApplySeq();
        //nlsCreditInfoVO.setLmtApplySeq(applySeq);
        //nlsCreditInfoVO = nlsCreditInfoService.queryByPk(nlsCreditInfoVO);

        try {
            /** 查询申请信息，获得征信查询接口所需的参数 **/
            String appNo = applySeq;
            log.info("开始进行征信规则参数准备,流水号:" + appNo);
            Objects.requireNonNull(nlsCreditInfoVO);
            if(!"02".equals(nlsCreditInfoVO.getApprvSts())){
                throw new BizException("授信审批状态不为通过状态，不查征信前置接口");
            }
            String cusName = nlsCreditInfoVO.getCusName();
            String certNo = nlsCreditInfoVO.getCertCode();
            String certType = nlsCreditInfoVO.getCertType();
            String authCd = appNo;
            String prdName = nlsCreditInfoVO.getPrdName(); // 产品名称
            String prdCode = nlsCreditInfoVO.getPrdCode(); // 产品编号
            String authDate = nlsCreditInfoVO.getCreateTime();//授权日期
            //String authTime = "";//授权时间
            String authTm = DateUtility.formatDateTime19To14(authDate);
            String date = DateTool.getCurrentDate();
            String StopDate = TimeUtil.addDay(date, 90);
            /** 查询产品获取征信userId */
            String prdId = Objects.requireNonNull(nlsCreditInfoVO.getPrdId());
            PrdInfoVO prdInfoVo = new PrdInfoVO();
            prdInfoVo.setPrdId(prdId);
            prdInfoVo = prdInfoService.queryByPk(prdInfoVo);
            //查询参数
            List<SCfgParamVO> params = sCfgParamService.queryToZx();
            String RprtUsr = null, RprtUsrBlngDept = null, valiDay = null;
            for (SCfgParamVO param : params) {
                if (param.getParamKey().equals("ZX_RprtUsr")) {
                    RprtUsr = param.getParamValue();
                    continue;
                }
                if (param.getParamKey().equals("ZX_RprtUsrBlngDept")) {
                    RprtUsrBlngDept = param.getParamValue();
                    continue;
                }
                if (param.getParamKey().equals("ZX_MS_VALID_DAY")) {
                    valiDay = param.getParamValue();
                    continue;
                }
            }

            /** 调用征信查询接口 **/
            final String queryAppType = "05", queryReason = "02", queryType = "0", authMd = "19", crdtRprtQryMd = "1";
            ZXCXA01QueryReports ZXQueryReports = new ZXCXA01QueryReports.Builder().withQryAppTp(queryAppType).withRprtUsr(RprtUsr).withRprtUsrBlngDept(RprtUsrBlngDept)
                    .withCustNm(cusName).withIdentTp(certType).withIdentNo(certNo).withQryRsn(queryReason).withQryTp(queryType)
                    .withAcqrngCustSrc("广州银行股份有限公司").withPdNm(prdName).withAuthMd(authMd)
                    .withCrdtRprtQryMd(crdtRprtQryMd)
                    .withAuthTm(authTm).withAuthStrtDt(date).withAuthStopDt(StopDate).build();
            String reportId = null;
            ZXJsonInfoVO queryReportVo = new ZXJsonInfoVO();
            queryReportVo.setCertCode(certNo);
            List<ZXJsonInfoVO> zxInfo = zxJsonInfoService.queryReportId(queryReportVo);
            if (zxInfo.size() > 0) {//有征信数据
                String reportTime = zxInfo.get(0).getReportTime();//最新征信报告时间
                reportTime = StringUtils.replace(reportTime, ".", "-");//转换yyyy-MM-dd HH:mm:ss
                log.info("当前用户征信报告日期" + reportTime);
                int day = TimeUtil.compareDates(TimeUtil.addDay(reportTime, Integer.parseInt(valiDay)), DateTool.getCurrentDateTime());
                if (day < 0) {//报告时间大于30天，调用征信接口
                    try {
                        ZXVO zxvoJson = zxCXA01Service.Zxservice(ZXQueryReports, params);
                        //ZXVO zxvoJson = getZxvoJson(ZXQueryReports,params);
                        reportId = (String) zxvoJson.getResp(); // not null
                    } catch (Exception e) {
                        throw new BizException("调用征信系统异常", e);
                    }
                    log.info("征信单笔查询接口调用完成,流水号:" + appNo + "，报告编号：" + reportId);
                } else {//大于当前时间，不进行落库
                    reportId = zxInfo.get(0).getReportId();
                    log.info("征信报告时间未到，不查询征信:" + appNo + "，报告编号：" + reportId);
                }
            } else {//无征信报告，调用征信接口
                try {
                    ZXVO zxvoJson = zxCXA01Service.Zxservice(ZXQueryReports, params);
                    //ZXVO zxvoJson = getZxvoJson(ZXQueryReports,params);
                    reportId = (String) zxvoJson.getResp(); // not null
                } catch (Exception e) {
                    throw new BizException("调用征信系统异常", e);
                }
                log.info("征信单笔查询接口调用完成,流水号:" + appNo + "，报告编号：" + reportId);
            }

            List<ZXHtmlInfoVO> zxHtmlInfoVOS = zxHtmlInfoService.queryAllZXHtmlReports(Arrays.asList(reportId));
            if (null == zxHtmlInfoVOS || zxHtmlInfoVOS.isEmpty()) {
                throw new BizException("调用征信系统异常");
            }
            String fpath = filePath + reportId + ".html";
            /*FileWriter fileWriter = new FileWriter(new File(fpath));
            fileWriter.write(zxHtmlInfoVOS.get(0).getContent());
            fileWriter.flush();
            fileWriter.close();*/

            OutputStreamWriter osw = new OutputStreamWriter(new FileOutputStream(fpath),"UTF-8");
            osw.write(zxHtmlInfoVOS.get(0).getContent());
            osw.flush();
            osw.close();

            /**
             * 保存征信报告文件上传记录
             */
            YedUploadRecordVO yedUploadRecordVO = new YedUploadRecordVO();
            yedUploadRecordVO.setApplSeq(nlsCreditInfoVO.getLmtApplySeq());
            yedUploadRecordVO.setCreateTime(new Date());
            yedUploadRecordVO.setDealType("1");//处理阶段（1-授信 2-用信 3-借据）
            yedUploadRecordVO.setFileType("Y03");//Y01-授权书 Y02-借款合同 Y03-征信报告
            yedUploadRecordVO.setFileUrl(fpath);
            yedUploadRecordVO.setPrdId(nlsCreditInfoVO.getPrdId());
            yedUploadRecordVO.setUpErrMsg("");
            yedUploadRecordVO.setRecordId(UUID.randomUUID().toString().replace("-",""));
            yedUploadRecordVO.setUpNum(0);
            yedUploadRecordVO.setUpSta(0);
            yedUploadRecordVO.setUpTime(new Date());
            yedUploadService.insert(yedUploadRecordVO);

            /**
             * 保存征信查询明细表
             */
            CreditQueryDetailVO creditQueryDetailVO = new CreditQueryDetailVO();
            creditQueryDetailVO.setSerno(UUID.randomUUID().toString().replace("-",""));
            creditQueryDetailVO.setCusId(nlsCreditInfoVO.getCusId());
            creditQueryDetailVO.setCusName(cusName);
            creditQueryDetailVO.setCertType(certType);
            creditQueryDetailVO.setCertCode(certNo);
            creditQueryDetailVO.setTransactionCode(nlsCreditInfoVO.getLmtApplySeq());
            creditQueryDetailVO.setPrdCode(prdCode);
            creditQueryDetailVO.setPrdName(prdName);
            creditQueryDetailVO.setReportId(reportId);
            creditQueryDetailVO.setReportTime(TimeUtil.getCurrentDateTime());
            creditQueryDetailVO.setRequestTime(TimeUtil.getCurrentDateTime());
            creditQueryDetailVO.setZxOpId("admin");
            creditQueryDetailVO.setInputBrId(nlsCreditInfoVO.getMainBrId());
            creditQueryDetailVO.setFinaBrId(nlsCreditInfoVO.getChargeoffBrId());
            Optional.ofNullable(creditQueryDetailVO).ifPresent(Try.ofConsumer(creditQueryDetailService::insertCreditQueryDetailVO));


        } catch (Exception e) {
            e.printStackTrace();
/*            nlsProcessBizVo.setExceptionFlag(true);
            nlsProcessBizVo.setExceptionMsg(e);*/

            log.error(Arrays.toString(e.getStackTrace()));
            if(zxCount.intValue() > 3){
                log.info("重试3次调用征信查询接口仍失败，请联系征信前置！！！");
                zxCount.set(1);
                ReqAlarmJudgementBean reqAlarmJudgementBean = new ReqAlarmJudgementBean();
                reqAlarmJudgementBean.setAlrmInf("重试3次调用征信查询接口仍失败，请联系征信前置！！！");
                try {
                    getrespAlarmJudgementBean(reqAlarmJudgementBean);
                } catch (Exception alarme) {
                    alarme.printStackTrace();
                    log.debug("调用告警接口异常！" + alarme.getMessage());
                }
                throw new Exception("【调用征信查询接口】申请流水号：" + applySeq + " 执行调用征信查询接口出现异常，异常信息为：" + e.getMessage());
            }
            while(zxCount.intValue() <= 3){
                Thread.sleep(30000);
                log.error("执行调用征信查询接口出现异常，出错信息为："+e.getMessage());
                log.info("开始重试第"+zxCount.intValue()+"次调用征信查询接口！！！");
                zxCount.incrementAndGet();
                doExecute(nlsProcessBizVo,nlsCreditInfoVO);
            }
        }
    }

    /**
     * 优e贷调用征信前置查询
     * @param queryReports
     * @param params
     * @return
     * @throws ESBException
     * @throws InterruptedException
     */
    public ZXVO getZxvoJson(ZXCXA01QueryReports queryReports, List<SCfgParamVO> params) throws ESBException, InterruptedException{
        ZXQueryBean zxQueryBean = new ZXQueryBean();
        zxQueryBean.setParams(params);
        zxQueryBean.setQueryReports(queryReports);
        EsbInvokeWrapper esbInvokeWrapper = new EsbInvokeWrapper(zxCXA01Service, zxQueryBean, nlsQueueSoltComnService);
        ZXVO zxvoJson = (ZXVO) esbInvokeWrapper.invoke3Threes();
        Objects.requireNonNull(zxvoJson, "优e贷调用征信前置查询返回对象为空!!!");
        return zxvoJson;
    }

    public static void main(String[] args) throws IOException {

       /*YedUploadRecordVO yedUploadRecordVO = new YedUploadRecordVO();
        yedUploadRecordVO.setApplSeq("00034324324");
        yedUploadRecordVO.setCreateTime(new Date());
        yedUploadRecordVO.setDealType("1");//处理阶段（1-授信 2-用信 3-借据）
        yedUploadRecordVO.setFileType("Y03");//Y01-授权书 Y02-借款合同 Y03-征信报告
        yedUploadRecordVO.setFileUrl("d:/test/test.html");
        yedUploadRecordVO.setPrdId("0004345");
        yedUploadRecordVO.setUpErrMsg("");
        yedUploadRecordVO.setRecordId(UUID.randomUUID().toString().replace("-",""));
        yedUploadRecordVO.setUpNum(0);
        yedUploadRecordVO.setUpSta(0);
        yedUploadRecordVO.setUpTime(new Date());
        yedUploadService.insert(yedUploadRecordVO);*/

    }

    /**
     *
     * 调用颖风写的告警判断服务
     *
     * @param reqAlarmJudgementBean
     * @return
     * @throws Exception
     * @author liyakui
     * @since 2019年1月28日 上午8:36:25
     * @version 1.0
     */
    public RespAlarmJudgementBean getrespAlarmJudgementBean(ReqAlarmJudgementBean reqAlarmJudgementBean) throws Exception {
        RespAlarmJudgementBean respAlarmJudgementBean = null;
        try {
            // 调用颖风写的告警判断服务
            reqAlarmJudgementBean.setMonObjNm("优e贷");
            reqAlarmJudgementBean.setMonObjSpfTpVal("外部接口");
            reqAlarmJudgementBean.setMonObjLctr(InetAddress.getLocalHost().getHostAddress());// 获取本机IP
            reqAlarmJudgementBean.setAlrmTmstmp(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format((new Date())));
            reqAlarmJudgementBean.setMonAlrmLvl("3");
            respAlarmJudgementBean = alarmJudgementService.alarmJudgement(reqAlarmJudgementBean);
            log.debug("调用告警判断返回码：【" + respAlarmJudgementBean.getRetCd() + "】，返回信息：【" + respAlarmJudgementBean.getRetMsg() + "】");
        } catch (Exception e) {
            log.info("调用告警接口异常！" + e.getMessage());
            throw e;
        }
        return respAlarmJudgementBean;
    }

    @Autowired
    private AlarmJudgementService alarmJudgementService;

}
